package com.hzmg.route.akka.dsl.sample2;

import akka.actor.ActorSystem;
import akka.http.javadsl.*;
import akka.http.javadsl.model.*;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.japi.function.Function;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;

import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HighLevelServerExample extends AllDirectives {

    public static void main(String[] args) throws Exception {

        ActorSystem system = ActorSystem.create();

        /*---------------------------------------------- 方法一 ----------------------------------------------*/
        final HighLevelServerExample app = new HighLevelServerExample();

        final Http http = Http.get(system);

        final CompletionStage<ServerBinding> binding = http.newServerAt("localhost", 8080).bind(app.createRoute());

        System.out.println("Type RETURN to exit");
        System.in.read();

        /*---------------------------------------------- 方法二 ----------------------------------------------*/
/*        final Materializer materializer = ActorMaterializer.create(system);

        Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
                Http.get(system).bind(ConnectHttp.toHost("localhost", 8080));

        final Function<HttpRequest, HttpResponse> requestHandler =
                new Function<HttpRequest, HttpResponse>() {
                    private final HttpResponse NOT_FOUND =
                            HttpResponse.create()
                                    .withStatus(404)
                                    .withEntity("Unknown resource!");

                    @Override
                    public HttpResponse apply(HttpRequest request) throws Exception {
                        Uri uri = request.getUri();
                        if (request.method() == HttpMethods.GET) {
                            if (uri.path().equals("/")) {
                                return
                                        HttpResponse.create()
                                                .withEntity("<html><body>Hello akkacloud-gateway!</body></html>");
                            } else if (uri.path().equals("/ping")) {
                                return HttpResponse.create()
                                        .withEntity("Success!");
                            } else if (uri.path().equals("/hello")) {
                                String name = uri.query().get("name").orElse("akkacloud-gateway-demo");

                                return
                                        HttpResponse.create()
                                                .withEntity(name);
                            } else {
                                return NOT_FOUND;
                            }
                        } else {
                            return NOT_FOUND;
                        }
                    }
                };

        CompletionStage<ServerBinding> serverBindingFuture =
                serverSource.to(Sink.foreach(connection -> {
                    System.out.println("Accepted new connection from " + connection.remoteAddress());
                    connection.handleWithSyncHandler(requestHandler, materializer);
                })).run(materializer);*/
    }

    public Route createRoute() {
        Route sampleRoute =
                parameterOptional("name", optName -> {
                    String name = optName.orElse("akkacloud-gateway-demo");
                    return complete(name);
                });
        return get(() -> concat(
                pathSingleSlash(() ->
                        complete(HttpEntities.create(ContentTypes.TEXT_HTML_UTF8, "<html><body>Hello akkacloud-gateway!</body></html>"))
                ),
                path("ping", () ->
                        complete("Success!")
                ),
                path("hello", () ->
                        sampleRoute)
        ));
    }
}
